package com.kexio.auth.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

/**
 * 性能监控切面
 * 监控方法执行时间和性能指标
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Aspect
@Order(50)
public class PerformanceMonitorAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(PerformanceMonitorAspect.class);
    
    // 性能阈值（毫秒）
    private static final long SLOW_THRESHOLD = 1000;
    private static final long WARNING_THRESHOLD = 3000;
    
    /**
     * 监控Service层方法性能
     */
    @Around("execution(* com.kexio..service.*.*(..))")
    public Object monitorServicePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "SERVICE");
    }
    
    /**
     * 监控Controller层方法性能
     */
    @Around("execution(* com.kexio..controller.*.*(..))")
    public Object monitorControllerPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "CONTROLLER");
    }
    
    /**
     * 监控带性能监控注解的方法
     */
    @Around("@annotation(com.kexio.auth.annotation.PerformanceMonitor)")
    public Object monitorAnnotatedMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "ANNOTATED");
    }
    
    /**
     * 执行性能监控
     */
    private Object monitorMethodPerformance(ProceedingJoinPoint joinPoint, String type) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = method.getName();
        
        long startTime = System.currentTimeMillis();
        Object result = null;
        boolean success = true;
        Throwable exception = null;
        
        try {
            result = joinPoint.proceed();
            return result;
        } catch (Throwable e) {
            success = false;
            exception = e;
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            
            // 记录性能日志
            logPerformance(type, className, methodName, executionTime, success, exception);
        }
    }
    
    /**
     * 记录性能日志
     */
    private void logPerformance(String type, String className, String methodName, 
                               long executionTime, boolean success, Throwable exception) {
        
        String status = success ? "SUCCESS" : "FAILED";
        String methodInfo = className + "." + methodName + "()";
        
        if (executionTime > WARNING_THRESHOLD) {
            logger.warn("🚨 [{}] 方法执行严重超时: {} - 耗时: {}ms - 状态: {}", 
                type, methodInfo, executionTime, status);
        } else if (executionTime > SLOW_THRESHOLD) {
            logger.warn("⚠️ [{}] 方法执行缓慢: {} - 耗时: {}ms - 状态: {}", 
                type, methodInfo, executionTime, status);
        } else {
            logger.debug("✅ [{}] 方法执行正常: {} - 耗时: {}ms - 状态: {}", 
                type, methodInfo, executionTime, status);
        }
        
        // 如果有异常，记录异常信息
        if (exception != null) {
            logger.error("❌ [{}] 方法执行异常: {} - 耗时: {}ms - 异常: {}", 
                type, methodInfo, executionTime, exception.getMessage());
        }
        
        // 记录详细的性能指标（可以集成到监控系统）
        recordPerformanceMetrics(type, className, methodName, executionTime, success);
    }
    
    /**
     * 记录性能指标到监控系统
     */
    private void recordPerformanceMetrics(String type, String className, String methodName, 
                                         long executionTime, boolean success) {
        try {
            // 这里可以集成到Micrometer、Prometheus等监控系统
            // 示例：记录到JVM指标
            String metricName = String.format("method.execution.time.%s.%s.%s", 
                type.toLowerCase(), className, methodName);
            
            // 可以使用MeterRegistry记录指标
            // meterRegistry.timer(metricName).record(executionTime, TimeUnit.MILLISECONDS);
            
            logger.debug("性能指标已记录: {} - {}ms - success: {}", metricName, executionTime, success);
            
        } catch (Exception e) {
            logger.error("记录性能指标失败", e);
        }
    }
}
